package com.eduagent.xwqeduagent.api.SpeechEvaluation;

import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;

/**
 * 语音评测结果处理工具类
 */
@Slf4j
public class SpeechEvaluationResult {

    /**
     * 解析XML评测结果，提取总分
     * @param xmlResult XML格式的评测结果
     * @return 总分，解析失败返回-1
     */
    public static double extractTotalScore(String xmlResult) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new InputSource(new StringReader(xmlResult)));
            
            // 查找不同类型的评测结果节点
            Element rootElement = document.getDocumentElement();
            
            // 先获取rec_paper节点下的内容
            NodeList recPaperNodes = rootElement.getElementsByTagName("rec_paper");
            if (recPaperNodes.getLength() > 0) {
                Element recPaper = (Element) recPaperNodes.item(0);
                
                // 尝试读取不同类型的评测结果
                NodeList readSyllableList = recPaper.getElementsByTagName("read_syllable");
                NodeList readWordList = recPaper.getElementsByTagName("read_word");
                NodeList readSentenceList = recPaper.getElementsByTagName("read_sentence");
                NodeList readChapterList = recPaper.getElementsByTagName("read_chapter");
                
                // 尝试获取总分
                double score = extractScoreFromNodeList(readSyllableList, "total_score");
                if (score >= 0) return score;
                
                score = extractScoreFromNodeList(readWordList, "total_score");
                if (score >= 0) return score;
                
                score = extractScoreFromNodeList(readSentenceList, "total_score");
                if (score >= 0) return score;
                
                score = extractScoreFromNodeList(readChapterList, "total_score");
                if (score >= 0) return score;
            }
            
            // 如果rec_paper下没找到，尝试顶层节点
            NodeList readSyllableList = rootElement.getElementsByTagName("read_syllable");
            NodeList readWordList = rootElement.getElementsByTagName("read_word");
            NodeList readSentenceList = rootElement.getElementsByTagName("read_sentence");
            NodeList readChapterList = rootElement.getElementsByTagName("read_chapter");
            
            // 尝试获取总分
            double score = extractScoreFromNodeList(readSyllableList, "total_score");
            if (score >= 0) return score;
            
            score = extractScoreFromNodeList(readWordList, "total_score");
            if (score >= 0) return score;
            
            score = extractScoreFromNodeList(readSentenceList, "total_score");
            if (score >= 0) return score;
            
            score = extractScoreFromNodeList(readChapterList, "total_score");
            if (score >= 0) return score;
            
            // 尝试查找FinalResult节点（精简模式）
            NodeList finalResultList = rootElement.getElementsByTagName("FinalResult");
            if (finalResultList.getLength() > 0) {
                Element finalResult = (Element) finalResultList.item(0);
                NodeList totalScoreList = finalResult.getElementsByTagName("total_score");
                if (totalScoreList.getLength() > 0) {
                    Element totalScoreElement = (Element) totalScoreList.item(0);
                    String value = totalScoreElement.getAttribute("value");
                    if (value != null && !value.isEmpty()) {
                        return Double.parseDouble(value);
                    }
                }
            }
            
            log.warn("未找到评测分数: {}", xmlResult);
            return -1;
        } catch (Exception e) {
            log.error("解析评测结果失败", e);
            return -1;
        }
    }
    
    /**
     * 从NodeList中提取分数属性值
     * @param nodeList 节点列表
     * @param attributeName 属性名
     * @return 分数，失败返回-1
     */
    private static double extractScoreFromNodeList(NodeList nodeList, String attributeName) {
        if (nodeList == null || nodeList.getLength() == 0) {
            return -1;
        }
        
        Element element = (Element) nodeList.item(0);
        if (!element.hasAttribute(attributeName)) {
            return -1;
        }
        
        String value = element.getAttribute(attributeName);
        if (value == null || value.isEmpty()) {
            return -1;
        }
        
        try {
            return Double.parseDouble(value);
        } catch (NumberFormatException e) {
            log.warn("属性 {} 的值 '{}' 无法解析为数字", attributeName, value);
            return -1;
        }
    }
    
    /**
     * 从XML评测结果中提取准确度分数
     * @param xmlResult XML格式的评测结果
     * @return 准确度分数，解析失败返回-1
     */
    public static double extractAccuracyScore(String xmlResult) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new InputSource(new StringReader(xmlResult)));
            
            Element rootElement = document.getDocumentElement();
            
            // 先检查rec_paper下的节点
            NodeList recPaperNodes = rootElement.getElementsByTagName("rec_paper");
            if (recPaperNodes.getLength() > 0) {
                Element recPaper = (Element) recPaperNodes.item(0);
                
                // 尝试读取句子或篇章节点
                NodeList readSentenceList = recPaper.getElementsByTagName("read_sentence");
                NodeList readChapterList = recPaper.getElementsByTagName("read_chapter");
                
                // 尝试获取准确度分数
                double score = extractScoreFromNodeList(readSentenceList, "accuracy_score");
                if (score >= 0) return score;
                
                score = extractScoreFromNodeList(readChapterList, "accuracy_score");
                if (score >= 0) return score;
            }
            
            // 如果rec_paper下没找到，尝试顶层节点
            NodeList readSentenceList = rootElement.getElementsByTagName("read_sentence");
            NodeList readChapterList = rootElement.getElementsByTagName("read_chapter");
            
            // 尝试获取准确度分数
            double score = extractScoreFromNodeList(readSentenceList, "accuracy_score");
            if (score >= 0) return score;
            
            score = extractScoreFromNodeList(readChapterList, "accuracy_score");
            if (score >= 0) return score;
            
            return -1;
        } catch (Exception e) {
            log.error("解析评测结果失败", e);
            return -1;
        }
    }
    
    /**
     * 从XML评测结果中提取流畅度分数
     * @param xmlResult XML格式的评测结果
     * @return 流畅度分数，解析失败返回-1
     */
    public static double extractFluencyScore(String xmlResult) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new InputSource(new StringReader(xmlResult)));
            
            Element rootElement = document.getDocumentElement();
            
            // 先检查rec_paper下的节点
            NodeList recPaperNodes = rootElement.getElementsByTagName("rec_paper");
            if (recPaperNodes.getLength() > 0) {
                Element recPaper = (Element) recPaperNodes.item(0);
                
                // 尝试读取句子或篇章节点
                NodeList readSentenceList = recPaper.getElementsByTagName("read_sentence");
                NodeList readChapterList = recPaper.getElementsByTagName("read_chapter");
                
                // 尝试获取流畅度分数
                double score = extractScoreFromNodeList(readSentenceList, "fluency_score");
                if (score >= 0) return score;
                
                score = extractScoreFromNodeList(readChapterList, "fluency_score");
                if (score >= 0) return score;
            }
            
            // 如果rec_paper下没找到，尝试顶层节点
            NodeList readSentenceList = rootElement.getElementsByTagName("read_sentence");
            NodeList readChapterList = rootElement.getElementsByTagName("read_chapter");
            
            // 尝试获取流畅度分数
            double score = extractScoreFromNodeList(readSentenceList, "fluency_score");
            if (score >= 0) return score;
            
            score = extractScoreFromNodeList(readChapterList, "fluency_score");
            if (score >= 0) return score;
            
            return -1;
        } catch (Exception e) {
            log.error("解析评测结果失败", e);
            return -1;
        }
    }
    
    /**
     * 检查评测是否成功（非乱读）
     * @param xmlResult XML格式的评测结果
     * @return 是否成功
     */
    public static boolean isSuccessful(String xmlResult) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new InputSource(new StringReader(xmlResult)));
            
            Element rootElement = document.getDocumentElement();
            
            // 检查是否被拒绝（乱读）- 先检查rec_paper下的节点
            NodeList recPaperNodes = rootElement.getElementsByTagName("rec_paper");
            if (recPaperNodes.getLength() > 0) {
                Element recPaper = (Element) recPaperNodes.item(0);
                NodeList readSentenceList = recPaper.getElementsByTagName("read_sentence");
                NodeList readWordList = recPaper.getElementsByTagName("read_word");
                NodeList readSyllableList = recPaper.getElementsByTagName("read_syllable");
                NodeList readChapterList = recPaper.getElementsByTagName("read_chapter");
                
                // 检查各种节点的is_rejected属性
                if (hasRejectedAttribute(readSentenceList)) return false;
                if (hasRejectedAttribute(readWordList)) return false;
                if (hasRejectedAttribute(readSyllableList)) return false;
                if (hasRejectedAttribute(readChapterList)) return false;
            }
            
            // 检查顶层节点
            NodeList readSentenceList = rootElement.getElementsByTagName("read_sentence");
            NodeList readWordList = rootElement.getElementsByTagName("read_word");
            NodeList readSyllableList = rootElement.getElementsByTagName("read_syllable");
            NodeList readChapterList = rootElement.getElementsByTagName("read_chapter");
            
            // 检查各种节点的is_rejected属性
            if (hasRejectedAttribute(readSentenceList)) return false;
            if (hasRejectedAttribute(readWordList)) return false;
            if (hasRejectedAttribute(readSyllableList)) return false;
            if (hasRejectedAttribute(readChapterList)) return false;
            
            // 检查是否有错误码
            NodeList retNodes = rootElement.getElementsByTagName("ret");
            for (int i = 0; i < retNodes.getLength(); i++) {
                Element element = (Element) retNodes.item(i);
                if (element.hasAttribute("value") && !"0".equals(element.getAttribute("value"))) {
                    return false;
                }
            }
            
            return true;
        } catch (Exception e) {
            log.error("解析评测结果失败", e);
            return false;
        }
    }
    
    /**
     * 检查节点列表中是否有被拒绝的节点
     * @param nodeList 节点列表
     * @return 是否有被拒绝的节点
     */
    private static boolean hasRejectedAttribute(NodeList nodeList) {
        if (nodeList == null || nodeList.getLength() == 0) {
            return false;
        }
        
        for (int i = 0; i < nodeList.getLength(); i++) {
            Element element = (Element) nodeList.item(i);
            if (element.hasAttribute("is_rejected") && 
                "true".equalsIgnoreCase(element.getAttribute("is_rejected"))) {
                return true;
            }
        }
        
        return false;
    }
} 